/*+***********************************************************************************
 Filename: 9k_mcu01_mycore_v01\src\mem\zh_sram_async_v01.v
 Description: sram with async read and wmask implement by verilog.
   dout is always change in effect with addr.
   data is only update on pos-edge of wclk when wen and wmask in effect.
              
 Modification:
   2025.08.16 Creation   H.Zheng

Copyright (C) 2025  Zheng Hui (hzheng@gzhu.edu.cn)

License: MulanPSL-2.0

***********************************************************************************-*/

module zh_sram_async_v01 #(parameter RAM_SIZE_IN_KB=1)(
  input wire [clogb2(RAM_SIZE_IN_KB*256-1)-1:0] addr,
  output wire [31:0] dout,

	input wire wclk, //write clock
	input wire wen, //write enable
  input  wire [3:0] wmask,
  input wire [31:0] din

);


reg [7:0] BRAM0 [0:RAM_SIZE_IN_KB*256-1];
reg [7:0] BRAM1 [0:RAM_SIZE_IN_KB*256-1];
reg [7:0] BRAM2 [0:RAM_SIZE_IN_KB*256-1];
reg [7:0] BRAM3 [0:RAM_SIZE_IN_KB*256-1];


//read
wire [7:0] dout0, dout1, dout2, dout3;

assign dout0 =  BRAM0[addr];
assign dout1 =  BRAM1[addr];
assign dout2 =  BRAM2[addr];
assign dout3 =  BRAM3[addr];

assign dout = {dout3, dout2, dout1, dout0};

//write
always @(posedge wclk) begin
  if(wen&wmask[0])
    BRAM0[addr] <= din[7:0];
end

always @(posedge wclk) begin
  if(wen&wmask[1])
    BRAM1[addr] <= din[15:8];
end

always @(posedge wclk) begin
  if(wen&wmask[2])
    BRAM2[addr] <= din[23:16];
end

always @(posedge wclk) begin
  if(wen&wmask[3])
    BRAM3[addr] <= din[31:24];
end


//
function integer clogb2;
    input integer depth;
        for (clogb2=0; depth>0; clogb2=clogb2+1)
            depth = depth >> 1;
endfunction

endmodule